package com.tamir.template.config;

import com.tamir.template.bean.TLogicNodeType;
import com.tamir.template.bean.TNode;
import com.tamir.template.exception.Errors;
import com.tamir.template.exception.TemplateException;
import com.tamir.template.express.handle.DefaultAttrValueHandle;
import com.tamir.template.express.handle.DefaultIfValueHandle;
import com.tamir.template.express.handle.DefaultListValueHandle;
import com.tamir.template.express.handle.DefaultLogicOperateValueHandle;
import com.tamir.template.express.handle.DefaultMapValueHandle;
import com.tamir.template.express.handle.ITExpressValueHandle;
import com.tamir.template.express.handle.DefaultTTextValueHandle;
import com.tamir.template.express.parse.DefaultIfHandleParse;
import com.tamir.template.express.parse.DefaultListHandleParse;
import com.tamir.template.express.parse.DefaultMapHandleParse;
import com.tamir.template.express.parse.DefaultTextHandleParse;
import com.tamir.template.express.parse.ILogicHandleParse;
import com.tamir.template.express.parse.LogicOperateHandleParser;
import com.tamir.template.starter.ITemplateStarter;
import com.tamir.template.starter.TemplateStarter;
import com.tamir.template.util.StringUtil;

import java.util.HashMap;
import java.util.Map;

/**
 * @author : tanggh
 * @description : 模版结点类型配置
 * @date : 2016/10/27
 */
public class TemplateNodeTypeConfig
{
    public static String NODE_TYPE_TEXT = "text";
    public static String NODE_TYPE_ATTRIBUTE = "attribute";
    public static String NODE_TYPE_LIST = "list";
    public static String NODE_TYPE_MAP = "map";
    public static String NODE_TYPE_OPERATOR = "operator";

    public static String NODE_TYPE_IF = "if";
    public static String NODE_TYPE_ELSE = "else";


    private static TemplateNodeTypeConfig instance = null;
    //注册的逻辑结点类型
    private Map<String, TLogicNodeType> registerLogicType;

    //注册的逻辑结点解析类
    private Map<String, ILogicHandleParse> registerLogicHandleParse;

    //表达式值获取处理类
    private Map<String, ITExpressValueHandle> registerExpressValueHandle;

    //相反逻辑类型注册(key为正结点,value为反结点{value表达式为<...> e.g<else>})
    private Map<TLogicNodeType, TLogicNodeType> registerOppositeLogicType;

    //template解析启动类
    private ITemplateStarter starter = null;

    public static TemplateNodeTypeConfig getInstance(){
        if(instance==null){
            synchronized(TemplateNodeTypeConfig.class){
                if(instance==null){
                    instance=new TemplateNodeTypeConfig();
                }
            }
        }
        return instance;
    }

    private TemplateNodeTypeConfig(){
        init();
    }
    private void init(){
        TLogicNodeType textType = new TLogicNodeType(NODE_TYPE_TEXT, "", "", false);
        TLogicNodeType attrType = new TLogicNodeType(NODE_TYPE_ATTRIBUTE, "${", "}", false);
        TLogicNodeType listType = new TLogicNodeType(NODE_TYPE_LIST, "<#list>", "</#list>", true);
        TLogicNodeType mapType = new TLogicNodeType(NODE_TYPE_MAP, "<#map>", "</#map>", true);
        TLogicNodeType ifType = new TLogicNodeType(NODE_TYPE_IF, "<#if>", "</#if>", true);
        TLogicNodeType elseType = new TLogicNodeType(NODE_TYPE_ELSE, "<else>", "", true);
        TLogicNodeType operateType = new TLogicNodeType(NODE_TYPE_OPERATOR, "", "", true);

        registerLogicType  = new HashMap<String, TLogicNodeType>();
        registerLogicType.put(NODE_TYPE_TEXT, textType);
        //直接获取属性值
        registerLogicType.put(NODE_TYPE_ATTRIBUTE, attrType);
        registerLogicType.put(NODE_TYPE_LIST, listType);
        registerLogicType.put(NODE_TYPE_MAP, mapType);
        registerLogicType.put(NODE_TYPE_IF, ifType);
        registerLogicType.put(NODE_TYPE_OPERATOR, operateType);
        //表达式解析
        registerLogicHandleParse = new HashMap<String, ILogicHandleParse>();
        registerLogicHandleParse.put(NODE_TYPE_TEXT, new DefaultTextHandleParse());
        registerLogicHandleParse.put(NODE_TYPE_ATTRIBUTE, new DefaultTextHandleParse());
        registerLogicHandleParse.put(NODE_TYPE_LIST, new DefaultListHandleParse());
        registerLogicHandleParse.put(NODE_TYPE_MAP, new DefaultMapHandleParse());
        registerLogicHandleParse.put(NODE_TYPE_IF, new DefaultIfHandleParse());
        registerLogicHandleParse.put(NODE_TYPE_OPERATOR, new LogicOperateHandleParser());


        //表达式和结点逻辑处理
        registerExpressValueHandle = new HashMap<String, ITExpressValueHandle>();
        registerExpressValueHandle.put(NODE_TYPE_TEXT, new DefaultTTextValueHandle());
        registerExpressValueHandle.put(NODE_TYPE_ATTRIBUTE, new DefaultAttrValueHandle());
        registerExpressValueHandle.put(NODE_TYPE_LIST, new DefaultListValueHandle());
        registerExpressValueHandle.put(NODE_TYPE_MAP, new DefaultMapValueHandle());
        registerExpressValueHandle.put(NODE_TYPE_IF, new DefaultIfValueHandle());
        registerExpressValueHandle.put(NODE_TYPE_OPERATOR, new DefaultLogicOperateValueHandle());

        registerOppositeLogicType = new HashMap<TLogicNodeType, TLogicNodeType>();
        registerOppositeLogicType.put(ifType, elseType);
        starter = new TemplateStarter();
    }

    public Map<String, TLogicNodeType> getRegisterLogicType()
    {
        return registerLogicType;
    }
    public TLogicNodeType getRegisterLogicTypeByKey(String key){
        TLogicNodeType nodeType = getRegisterLogicType().get(key);
        if(nodeType == null){
            throw new TemplateException(Errors.express_not_registered);
        }
        return nodeType;
    }
    public Map<String, ILogicHandleParse> getRegisterLogicHandleParse()
    {
        return registerLogicHandleParse;
    }

    public Map<String, ITExpressValueHandle> getRegisterExpressValueHandle()
    {
        return registerExpressValueHandle;
    }

    public ITemplateStarter getTemplateStarter()
    {
        return starter;
    }

    /**
     * 获取node的值处理类
     * @param node
     * @return
     */
    public ITExpressValueHandle getITExpressValueHandle(TNode node)
    {
        ITExpressValueHandle handle = null;
        if(node != null && node.gettLogicType() != null){
            handle= TemplateNodeTypeConfig.getInstance()
                    .getRegisterExpressValueHandle().get(node
                            .gettLogicType().gettLogicType());
        }
        if (handle == null)
        {
            throw new TemplateException(Errors.logic_type_value_handle_not_registered, node
                    .gettLogicType().gettLogicType());
        }
        return handle;
    }

    public ILogicHandleParse getILogicHandleParse(String key){
        ILogicHandleParse parse = null;
        if(StringUtil.isNotEmpty(key)){
            parse = TemplateNodeTypeConfig.getInstance().getRegisterLogicHandleParse().get(key);
        }
        if(parse == null){
            throw new TemplateException(Errors.logic_handle_parse_not_registered);
        }
        return parse;
    }

    /**
     * 获取结点的相反结点,如<#if> <else></#if>
     * @param logicNodeType
     * @return
     */
    public TLogicNodeType getOppositeLogicType(TLogicNodeType logicNodeType){
        if(logicNodeType != null){
            return registerOppositeLogicType.get(logicNodeType);
        }
        return null;
    }
}
